[NVBug: 6563509] Drop Phi-3-vision / Phi-4-multimodal PTQ support - #2115
Conversation
… fails
get_model() builds a throwaway skeleton under
init_empty_weights(include_buffers=True) purely to size the model for
infer_auto_device_map. include_buffers=True makes accelerate push a global
torch.device("meta") context, so every tensor constructed in __init__ lands on
meta -- not just parameters and buffers. Remote-code checkpoints written before
Transformers v5 routinely derive scalar hyperparameters from real tensors there
(Phi-4-multimodal's conformer subsampling does int(torch.tensor(...))), which
raises "Tensor.item() cannot be called on meta tensors" and killed the whole
run before from_pretrained was ever reached.
Retry the skeleton without the global meta context, and if that also fails,
warn and skip the memory estimate instead of aborting -- from_pretrained can
still map the model on its own. Losing the estimate only costs the automatic
max_memory shrink, which --use_seq_device_map and --gpu_max_memory_percentage
already cover.
Note this does not by itself make Phi-4-multimodal-instruct loadable: its
remote code additionally needs transformers <4.52 (Phi4MMModel relies on
PreTrainedModel inheriting GenerationMixin, which peft's get_peft_model calls
into) and declares _tied_weights_keys as a list, which Transformers 5.x
rejects. Both are outside ModelOpt.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
Both ship remote code that predates Transformers v5 and no longer loads on any version this repo supports (transformers>=4.57,<5.15): - Phi-4-multimodal needs transformers<4.52. Its __init__ calls peft.get_peft_model on Phi4MMModel, which reads prepare_inputs_for_generation -- present only while PreTrainedModel still inherited GenerationMixin. Verified loading at 4.48.2 / 4.49.0 / 4.50.0 / 4.51.3, failing at 4.53.3 / 4.56.2 / 4.57.1 with AttributeError. - Both declare _tied_weights_keys as a list; Transformers 5.x calls .keys() on it in post_init and raises AttributeError. - Phi-4-multimodal additionally computes int(torch.tensor(...)) in __init__, which Transformers 5.x's meta-device from_pretrained cannot evaluate. The model card pins transformers==4.48.2 / peft==0.13.2, so there is no overlap with our floor and nothing on our side can bridge it. Removes the support-matrix row, the phi4mm model type, the multimodal-detection heuristics that only ever matched these two (vision_lora, audio_processor, embd_layer.image_embd_layer), the Phi3Image/PhiImage embedding-export exclusions, and modelopt_recipes/huggingface/phi4mm/. Text-only Phi-3/Phi-4 and Phi-3.5-MoE are natively supported by transformers and are untouched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe change removes PTQ support for Phi-3-vision and Phi-4-multimodal. It removes related detection, export handling, documentation, and recipes. It also skips device-map memory estimation when model skeleton construction fails. ChangesPTQ support removal
HF PTQ loading fallback
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant HFPTQ as HF PTQ
participant Skeleton as Meta skeleton construction
participant DeviceMap as Device-map inference
HFPTQ->>Skeleton: Build skeleton without buffers
alt Construction succeeds
HFPTQ->>DeviceMap: Infer device map
else Construction fails
Skeleton-->>HFPTQ: Return None and warning
HFPTQ->>HFPTQ: Skip memory estimation
end
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✨ Finishing Touches 💡 1⚔️ Resolve merge conflicts 💡
🧪 Generate unit tests (beta)
Comment |
|
There was a problem hiding this comment.
Warning
CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.
Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@examples/hf_ptq/example_utils.py`:
- Around line 898-903: Update the fallback path after skeleton construction
fails, before the final from_pretrained load, to populate GPU entries in
model_kwargs["max_memory"] using the configured GPU memory percentage when model
is None. Preserve any limit already established by sequential device mapping,
and keep the existing fallback loading behavior unchanged.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: c15bf192-fc6f-44b2-86ab-c408eea1be07
📒 Files selected for processing (10)
CHANGELOG.rstexamples/hf_ptq/README.mdexamples/hf_ptq/example_utils.pyexamples/hf_ptq/hf_ptq.pymodelopt/torch/export/layer_utils.pymodelopt/torch/export/model_utils.pymodelopt_recipes/huggingface/phi4mm/ptq/README.mdmodelopt_recipes/huggingface/phi4mm/ptq/disabled_quantizers.yamlmodelopt_recipes/huggingface/phi4mm/ptq/nvfp4-kv_fp8_cast.yamlmodelopt_recipes/ptq.md
💤 Files with no reviewable changes (5)
- examples/hf_ptq/hf_ptq.py
- modelopt_recipes/huggingface/phi4mm/ptq/nvfp4-kv_fp8_cast.yaml
- modelopt_recipes/huggingface/phi4mm/ptq/README.md
- modelopt_recipes/huggingface/phi4mm/ptq/disabled_quantizers.yaml
- modelopt/torch/export/model_utils.py
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2115 +/- ##
==========================================
- Coverage 78.60% 76.71% -1.90%
==========================================
Files 522 522
Lines 60167 62613 +2446
==========================================
+ Hits 47294 48033 +739
- Misses 12873 14580 +1707
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| config_dtype = _get_config_dtype(config_for_init) | ||
| model_kwargs2 = _apply_dtype_to_config( | ||
| model_kwargs, config_dtype, architecture, apply_config_dtype=True | ||
| # When computing the device_map, assuming bfloat16 precision by default, |
There was a problem hiding this comment.
how about we make this a util function?
There was a problem hiding this comment.
Done in 8444c11 — extracted as _build_meta_skeleton(), placed next to the other get_model helpers (_resolve_init_config / _get_config_dtype). get_model is now a single call, and the fallback is unit-testable on its own: verified all three paths (tier-1 succeeds / tier-1 fails on meta and tier-2 succeeds / both fail returning None with one warning).
There was a problem hiding this comment.
Follow-up: _build_meta_skeleton() simplified further in 1b062da. The two-tier retry is gone — it is now a single include_buffers=False build, because that is what Transformers' own from_pretrained uses and the old include_buffers=True probe was stricter than the loader it was predicting. Details in the design thread.
There was a problem hiding this comment.
Final state on this one: the helper you asked me to extract has now been deleted outright in 4e0157d. Sizing the device map from the checkpoint index removes the need to construct a model at all, so _build_meta_skeleton and everything that fed it (_resolve_init_config, the from_config resolution, the accelerate imports) are gone. Net 74 lines lighter than before the extraction.
There was a problem hiding this comment.
Superseded by 701180e — this code is back to its original form on main.
example_utils.py and its tests are restored to main except for the Phi-specific multimodal-detection heuristics. The meta-device skeleton, infer_auto_device_map, and the --gpu_max_mem_percentage cap all keep their original behavior, so there is nothing left in this thread to act on.
Reasoning: the cap is wanted exactly where it already fires — when the model is already offloading to CPU, where it costs little and the headroom is required. Every alternative explored on this branch (a more permissive skeleton, sizing from the checkpoint index, an unconditional budget) either changed behavior for models that fit today or moved the guard somewhere it does not belong, and all of it was for a crash that only ever affected the checkpoints this PR removes. NVBug 6563509 is resolved by dropping Phi-4-multimodal, not by changing the loader.
|
|
||
| > *This is a subset of the models supported. For the full list please check the [TensorRT-LLM support matrix](https://nvidia.github.io/TensorRT-LLM/reference/precision.html#support-matrix)* | ||
|
|
||
| > *Phi-3-vision and Phi-4-multimodal were dropped from this matrix: their bundled |
There was a problem hiding this comment.
no need to explain here.
There was a problem hiding this comment.
Done in 8444c11 — note removed. The CHANGELOG entry under 0.46 Backward Breaking Changes carries the explanation.
meenchen
left a comment
There was a problem hiding this comment.
Bot review (gpt-5.6-sol) — DM the bot to share feedback.
The fallback direction is reasonable, but there is a correctness issue in the failure path and the breaking Phi-3-vision removal is not supported by the compatibility evidence presented. No tests were added for the new two-attempt/fallback behavior.
Design review: the problem is to prevent an optional meta skeleton used for device-map sizing from aborting an otherwise viable from_pretrained load. Existing alternatives are (1) the repo's build_meta_causal_lm pattern in modelopt/torch/utils/plugins/model_load_utils.py, which uses init_empty_weights(include_buffers=False) directly, (2) relying on Accelerate/Transformers' existing device_map="auto" plus an explicit max_memory, or (3) extending/using Transformers' safe meta creation patches. The PR body explains why include_buffers=True is hazardous and why it retries, but does not compare why retrying is preferable to always using the existing include_buffers=False pattern or delegating directly to from_pretrained. Please document that choice, as required by the design-review gate.
Additional comments (outside the PR diff):
examples/hf_ptq/example_utils.py:909— > Bot comment.
The suggested --gpu_max_memory_percentage mitigation has no effect when both skeleton attempts fail. In this branch model is None, so the later elif model is not None block never scales max_memory or places it in model_kwargs; from_pretrained(device_map="auto") therefore uses its default memory budget regardless of this flag. Please either pass an appropriately scaled max_memory in the fallback path or remove this recommendation. Add mocked tests for first-attempt failure/second-attempt success and both-attempts failure; those would also pin whether infer_auto_device_map is skipped and whether the advertised memory limit reaches from_pretrained.
|
|
||
| **Deprecations** | ||
|
|
||
| - Drop PTQ support for **Phi-3-vision** and **Phi-4-multimodal**. Their bundled remote code predates Transformers v5 and no longer loads on the versions this repo requires (``transformers>=4.57``): Phi-4-multimodal needs ``transformers<4.52`` because it reaches ``prepare_inputs_for_generation`` through ``peft``, which requires ``PreTrainedModel`` to still inherit ``GenerationMixin``, and both models declare ``_tied_weights_keys`` as a list, which Transformers 5.x rejects. Removes the ``phi4mm`` model type, its multimodal-detection heuristics (``vision_lora`` / ``audio_processor`` / ``embd_layer.image_embd_layer``), the ``Phi3Image`` / ``PhiImage`` embedding-export exclusions, and the ``modelopt_recipes/huggingface/phi4mm/`` recipes. |
There was a problem hiding this comment.
Bot comment.
The supplied evidence does not establish that Phi-3-vision is unloadable across the supported range. The dependency floor and CI matrix explicitly include Transformers 4.57, while the listed Phi-3 blocker (_tied_weights_keys as a list) is described as a Transformers 5.x failure; the version matrix in the PR body only tests Phi-4-MM. Since this is a breaking support removal, please provide/test the Phi-3-vision failure on 4.57 (and identify its blocker), or retain Phi-3-vision support and scope the deletion/documentation to Phi-4-MM.
There was a problem hiding this comment.
Fair reading of the evidence, but we are keeping Phi-3-vision in the removal.
You are right about what was and was not proven. Phi-3-vision has no get_peft_model call, so it does not have the transformers-4.52 blocker — that one is Phi-4-MM only. The defect I verified for it is _tied_weights_keys declared as a list (modeling_phi3_v.py:1214), which is a Transformers 5.x failure, and I did not run it end-to-end on 4.57.
We are dropping it anyway, for product reasons rather than a 4.57 repro: Phi-3-vision is the older, superseded model, and Phi-4-multimodal is its replacement. If we cannot support the successor there is no reason to carry the predecessor — it is strictly the weaker model and nobody starting today would pick it over Phi-4-MM.
The technical direction agrees. Phi-3-vision is confirmed broken on Transformers 5.x, and per the 0.46 changelog we already bumped the floor to 4.57 with "Transformers 4.x support will be dropped in a future release". So the best case for keeping it is a support window that closes on its own within a release or two, on a model whose remote code Microsoft is not updating. The same reasoning already applied to VILA / NVILA in this release.
Happy to reopen if someone has an active Phi-3-vision workflow on 4.57.
0.46 is the release these land in, not the still-open 0.47 section. The Phi drop goes under Backward Breaking Changes next to the VILA / NVILA entry, which removed model support for the same reason (bundled remote code pinned below our transformers floor); the skeleton fallback goes under Bug Fixes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
… note - Extract the two-attempt skeleton build into `_build_meta_skeleton()` next to the other `get_model` helpers (@cjluo-nv). `get_model` now reads as one line, and the fallback logic is unit-testable in isolation. - Fix the OOM hint in the fallback warning. It named `--gpu_max_memory_percentage`, which does not exist -- the flag is `--gpu_max_mem_percentage` -- and on its own that flag has no effect when the skeleton fails: `model_kwargs["max_memory"]` is only set by the `_disk_offload` and `use_seq_device_map` paths, so the skipped `infer_auto_device_map` branch never applies it. Point at `--use_seq_device_map` (which does apply the percentage) and `--batch_size` instead (@coderabbitai). Not adopting the suggested unconditional cap: the original code only shrinks `max_memory` when `infer_auto_device_map` reports a CPU spill, so capping whenever the skeleton fails would force CPU offload onto models that currently fit entirely on GPU. - Drop the support-matrix explanation note; the CHANGELOG covers it (@cjluo-nv). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
meenchen
left a comment
There was a problem hiding this comment.
Bot review (gpt-5.6-sol) — DM the bot to share feedback.
Re-review: the prior max-memory failure-path concern is addressed by the revised warning, and extracting _build_meta_skeleton makes the fallback testable. However, two critical items remain: no tests were committed for the new retry/skip behavior, and the Phi-3-vision compatibility claim still overstates the evidence (the author explicitly confirmed it was not tested on supported Transformers 4.57 and is being removed for product reasons). The changelog also retains the obsolete CLI spelling. Design review remains incomplete: the problem is preventing an optional sizing skeleton from aborting the real load; alternatives include the repo's direct include_buffers=False approach in modelopt/torch/utils/plugins/model_load_utils.py, delegating to Transformers/Accelerate device_map="auto" with max_memory, and Transformers' safe meta-creation patches. The PR discusses the last two and why global-meta creation is hazardous, but still does not explain why the two-tier retry is preferable to always using the existing include_buffers=False pattern. Please document that tradeoff before approval.
| return hf_config | ||
|
|
||
|
|
||
| def _build_meta_skeleton(from_config, config_for_init, model_kwargs, architecture): |
There was a problem hiding this comment.
Bot comment.
This addresses the implementation shape, but the prior critical test request is still unresolved: none of the changed files adds tests for this helper. Please commit mocked coverage for (1) include_buffers=True succeeding, (2) the first attempt failing and include_buffers=False succeeding, and (3) both attempts failing with one warning. The last case should also exercise get_model to pin that infer_auto_device_map is skipped while from_pretrained is still called. Existing test_get_model_* tests only exercise a successful skeleton.
There was a problem hiding this comment.
Both points addressed in 1b062da — and you were right that the retry needed justifying. It did not survive the justification, so it is gone.
Design. The probe answers exactly one boolean: will the model spill to CPU, so should max_memory get the gpu_max_mem_percentage haircut. (inferred_device_map has two references in the file — it is built, tested with "cpu" in .values(), and discarded.) infer_auto_device_map reaches that via compute_module_sizes, which is tensor.numel() * dtype_byte_size(tensor.dtype) — shapes and dtypes, never storage.
So the probe only has to reproduce the module tree, and the binding constraint is that it must be no stricter than the loader it predicts:
how from_pretrained builds the model |
|
|---|---|
| transformers 4.57.6 | init_contexts = [no_init_weights(), init_empty_weights()] — include_buffers defaults to False (modeling_utils.py:4378) |
| transformers 5.5.4 | torch.device("meta") + meta_device_safe_creation_ops() (redirects torch.linspace to CPU) |
| old probe | bare torch.device("meta"), no patch |
include_buffers=True was stricter than both. accelerate implements it as a bare global device context, so it captures scratch arithmetic in __init__ that has nothing to do with weights. Transformers added meta_device_safe_creation_ops precisely because pre-v5 remote code derives scalars that way. A model doing int(torch.tensor(...)) in __init__ loads fine via from_pretrained on 4.x and 5.x, but died in our probe — an optimization killing runs it exists only to speed up.
So the answer to "why not just use the existing include_buffers=False pattern" is: we should, and now do. Single build, no retry loop, no noqa: PERF203, no error accumulation. Measured cost on real checkpoints is nil — Qwen3-8B and DeepSeek-R1-Distill-Llama-70B both retain 0.0 MiB and produce identical sized totals (15.256 / 131.417 GiB) either way, for +0.09s and +0.19s.
One note on build_meta_causal_lm: it uses include_buffers=False for a different reason, not as a general preference. Its skeleton is kept and has real weights loaded into it under FSDP2, and inv_freq / original_inv_freq are persistent=False (verified absent from state_dict()), so they are computed at init and never loaded — on meta they would stay meta. It needs real buffers; this probe needs none. Same call, opposite motivation.
Tests. Added in tests/examples/hf_ptq/test_example_utils.py: the probe uses permissive patching, it survives a meta-hostile __init__ (int(torch.tensor(...)), the Phi-4-MM shape), it returns None with a warning on failure, and get_model skips infer_auto_device_map while still calling from_pretrained — asserting no max_memory cap is invented, per the CodeRabbit thread. 32 passed in the file.
There was a problem hiding this comment.
Follow-up: the helper this thread was about no longer exists as of 4e0157d. _build_meta_skeleton and its four tests are gone — the device map is now sized from the checkpoint on disk, so no model is constructed and there is no fallback path to cover. The replacement _checkpoint_size_bytes has its own tests (index metadata, shard-sum fallback, malformed index) plus get_model tests for capping only when the weights exceed the GPU budget, no cap when the size is unknown, and an assertion that nothing is constructed during sizing.
There was a problem hiding this comment.
Superseded by 701180e — this code is back to its original form on main.
example_utils.py and its tests are restored to main except for the Phi-specific multimodal-detection heuristics. The meta-device skeleton, infer_auto_device_map, and the --gpu_max_mem_percentage cap all keep their original behavior, so there is nothing left in this thread to act on.
Reasoning: the cap is wanted exactly where it already fires — when the model is already offloading to CPU, where it costs little and the headroom is required. Every alternative explored on this branch (a more permissive skeleton, sizing from the checkpoint index, an unconditional budget) either changed behavior for models that fit today or moved the guard somewhere it does not belong, and all of it was for a crash that only ever affected the checkpoints this PR removes. NVBug 6563509 is resolved by dropping Phi-4-multimodal, not by changing the loader.
| - Remove the deprecated ``examples/llm_qad`` Megatron-LM QAD example (deprecated in 0.45). Use the `megatron_bridge QAD example <https://github.com/NVIDIA/Model-Optimizer/tree/main/examples/megatron_bridge#quantization-aware-distillation-qad>`_ instead, which provides a simpler Python-based interface and better model coverage. | ||
| - Dropped VILA / NVILA vision-language model support in ``examples/hf_ptq``. VILA's modeling code requires ``transformers<=4.50.0``, which conflicts with ModelOpt's minimum supported ``transformers`` version. The VILA-specific bootstrap (repo clone, ``requirements-vila.txt``) and loading paths in ``example_utils.py`` have been removed. | ||
| - Dropped **Phi-3-vision** and **Phi-4-multimodal** PTQ support in ``examples/hf_ptq`` (NVBug 6563509). Their bundled remote code predates Transformers v5 and no longer loads on any version ModelOpt supports (``transformers>=4.57``): Phi-4-multimodal requires ``transformers<4.52`` because it reaches ``prepare_inputs_for_generation`` through ``peft``, which needs ``PreTrainedModel`` to still inherit ``GenerationMixin``, and both models declare ``_tied_weights_keys`` as a list, which Transformers 5.x rejects. The support-matrix row, the ``phi4mm`` model type, the multimodal-detection heuristics that only ever matched these two (``vision_lora`` / ``audio_processor`` / ``embd_layer.image_embd_layer``), the ``Phi3Image`` / ``PhiImage`` embedding-export exclusions, and the ``modelopt_recipes/huggingface/phi4mm/`` recipes have been removed. Text-only Phi-3/Phi-4 and Phi-3.5-MoE are unaffected. | ||
|
|
There was a problem hiding this comment.
Bot comment.
This still says Phi-3-vision “no longer loads on any version ModelOpt supports,” but the author’s reply confirms it was not tested on supported Transformers 4.57 and that its identified _tied_weights_keys blocker is a 5.x failure. If the removal is a product decision because the model is superseded, document that rationale instead of making an unverified compatibility claim (or provide the 4.57 repro/blocker).
There was a problem hiding this comment.
Addressed in 17dfd3b — you were right that the entry was making an unverified claim.
The changelog now splits the two rationales. Phi-4-multimodal is described as unloadable on any supported version, which the matrix does support. Phi-3-vision is described as a supersession removal: "dropped alongside it: it is the older, superseded model in the same family, so with its successor unsupportable there is no reason to keep carrying the predecessor." A parenthetical records what was actually verified — it shares the list-valued _tied_weights_keys defect so is broken on Transformers 5.x, but does not hit the peft blocker. No 4.57 claim is made for it. The PR description carries the same split.
| - Fix ``examples/vllm_serve`` serving shared experts uncalibrated: their ``gate_proj``/``up_proj`` quantizer keys were not merged into ``gate_up_proj`` on reload, so they matched no module and were dropped. | ||
| - Fix Qwen3-VL MoE PTQ failing on ``transformers>=5.12`` with ``AttributeError: 'QuantQwen3VLMoeTextExperts' object has no attribute 'hidden_size'`` (NVBug 6518551). transformers 5.12 moved ``Qwen3VLMoeTextExperts`` onto the standard ``@use_experts_implementation`` fused layout (``hidden_size``/``expert_dim`` renamed to ``hidden_dim``/``intermediate_dim``, ``gate_up_proj`` transposed to ``(num_experts, 2*intermediate_dim, hidden_dim)``, two ``F.linear`` calls per expert), but the legacy ``_QuantQwen3VLMoeTextExperts`` wrapper stayed statically registered and shadowed on-the-fly detection. The new layout is now left to ``register_fused_experts_on_the_fly``, which claims it with the generic ``_QuantFusedExperts``; the legacy wrapper is still registered on ``transformers<5.12``, whose ``torch.bmm``-based forward the generic wrapper cannot intercept. | ||
| - Fix ``examples/hf_ptq`` multi-node FSDP2 export (``--use_fsdp2``) failing with ``RuntimeError: Cannot set version_counter for inference tensor``. ``export_quantized`` wrapped its whole body in ``torch.inference_mode()``, so the full params gathered by ``get_model_state_dict(full_state_dict=True)`` were inference tensors and the subsequent ``state_dict()`` -> ``param.detach()`` could not set their version counter. The export context is now ``torch.no_grad()``, which still disables autograd but keeps the gathered params as normal tensors. | ||
| - Fix ``examples/hf_ptq`` aborting the whole model load when the throwaway meta-device skeleton it builds to size ``infer_auto_device_map`` cannot be constructed (NVBug 6563509). ``init_empty_weights(include_buffers=True)`` pushes a global ``torch.device("meta")`` context, so remote-code checkpoints that derive scalar hyperparameters from real tensors in ``__init__`` failed with ``Tensor.item() cannot be called on meta tensors`` before ``from_pretrained`` was ever reached. The skeleton is now retried without the global meta context, and if that also fails the memory estimate is skipped with a warning instead of failing the run; ``--use_seq_device_map`` and ``--gpu_max_memory_percentage`` cover the lost heuristic. |
There was a problem hiding this comment.
Bot comment.
The fallback warning was corrected, but this changelog entry still uses the nonexistent --gpu_max_memory_percentage spelling and implies that flag independently covers the lost estimate. The actual option is --gpu_max_mem_percentage, and in this failure path it only takes effect with --use_seq_device_map; please mirror the accurate warning text here.
There was a problem hiding this comment.
Addressed — first in 1b062da, and the entry has since been rewritten again in 4e0157d.
You were right on both parts: the changelog still carried the nonexistent --gpu_max_memory_percentage spelling, and it implied that flag alone covered the lost estimate when in this path it only takes effect together with --use_seq_device_map.
That text is now gone entirely rather than corrected, because the fallback it described no longer exists: the device map is sized from the checkpoint on disk instead of from a constructed model, so there is no skeleton to fail and no estimate to lose. The entry now describes that mechanism, and the only remaining degradation is "size unreadable → no cap applied", the same as before.
There was a problem hiding this comment.
Superseded by 701180e — this code is back to its original form on main.
example_utils.py and its tests are restored to main except for the Phi-specific multimodal-detection heuristics. The meta-device skeleton, infer_auto_device_map, and the --gpu_max_mem_percentage cap all keep their original behavior, so there is nothing left in this thread to act on.
Reasoning: the cap is wanted exactly where it already fires — when the model is already offloading to CPU, where it costs little and the headroom is required. Every alternative explored on this branch (a more permissive skeleton, sizing from the checkpoint index, an unconditional budget) either changed behavior for models that fit today or moved the guard somewhere it does not belong, and all of it was for a crash that only ever affected the checkpoints this PR removes. NVBug 6563509 is resolved by dropping Phi-4-multimodal, not by changing the loader.
The probe exists only to answer one boolean -- will this model spill to CPU, so
should max_memory get the gpu_max_mem_percentage haircut. `infer_auto_device_map`
gets there via `compute_module_sizes`, which reads `tensor.numel()` and
`tensor.dtype` and never touches storage. So the probe only has to reproduce the
module tree, and it must be no stricter than the loader it predicts.
`include_buffers=True` was stricter than both loaders:
- Transformers 4.x `from_pretrained` builds under `init_empty_weights()`, whose
`include_buffers` defaults to False (modeling_utils.py:4378).
- Transformers 5.x builds under `torch.device("meta")` plus
`meta_device_safe_creation_ops()`, which redirects `torch.linspace` to CPU
precisely so pre-v5 remote code that derives scalars in `__init__` keeps
working.
accelerate implements `include_buffers=True` as a bare global `torch.device("meta")`
context, which also captures scratch arithmetic in `__init__` that has nothing to
do with weights. A model doing `int(torch.tensor(...))` there loads fine through
`from_pretrained` on both 4.x and 5.x but died in our probe -- an optimization
killing runs it was only meant to speed up.
Dropping to a single `include_buffers=False` build removes the retry loop, the
PERF203 waiver, and the two-attempt error accumulation. Measured cost on real
checkpoints is nil: Qwen3-8B and DeepSeek-R1-Distill-Llama-70B both report 0.0 MiB
retained and identical sized totals (15.256 / 131.417 GiB) either way, for +0.09s
and +0.19s respectively.
Adds the coverage requested in review: the probe uses permissive patching, it
survives a meta-hostile `__init__`, it returns None and warns on failure, and
`get_model` skips `infer_auto_device_map` while still calling `from_pretrained`
without inventing a max_memory cap.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
meenchen
left a comment
There was a problem hiding this comment.
Bot review (gpt-5.6-sol) — DM the bot to share feedback.
Re-review: the implementation concern and most prior comments are addressed. The max-memory finding was correctly resolved by fixing the warning rather than inventing a fallback cap; the CLI spelling is now correct; and the new tests cover permissive skeleton construction, a meta-hostile initializer, helper failure/warning, and the get_model skip-and-continue path.
One important prior comment remains unresolved: the changelog still says Phi-3-vision cannot load on any supported Transformers version, although the author confirmed it was not tested on supported 4.57 and is being removed for product/supersession reasons. The PR body also remains stale: it describes and claims testing for a two-attempt retry that commit 1b062da36 removed. Please update both to describe the current single include_buffers=False probe and accurately characterize the Phi-3-vision removal.
Design review: the problem is preventing an optional model-sizing skeleton from aborting a potentially viable real load. The relevant alternatives are the repo's existing build_meta_causal_lm pattern (modelopt/torch/utils/plugins/model_load_utils.py) using include_buffers=False, delegating sizing/mapping to Accelerate/Transformers via device_map="auto" and max_memory, and Transformers' patched safe-meta construction. The author's design-thread reply now gives a convincing reason to adopt the first option, and the code/docstring do so, but the required PR-body rationale is not yet updated and currently documents the superseded retry design.
This PR also deletes recipe files carrying SPDX/license headers, so the licensing-related file removal should receive human sign-off before merge.
| - Remove the deprecated ``examples/llm_autodeploy`` example (deprecated in 0.45). Use TensorRT-LLM's `AutoDeploy <https://github.com/NVIDIA/TensorRT-LLM/tree/main/examples/auto_deploy>`_ directly together with ModelOpt PTQ in ``examples/hf_ptq``. | ||
| - Remove the deprecated ``examples/llm_qad`` Megatron-LM QAD example (deprecated in 0.45). Use the `megatron_bridge QAD example <https://github.com/NVIDIA/Model-Optimizer/tree/main/examples/megatron_bridge#quantization-aware-distillation-qad>`_ instead, which provides a simpler Python-based interface and better model coverage. | ||
| - Dropped VILA / NVILA vision-language model support in ``examples/hf_ptq``. VILA's modeling code requires ``transformers<=4.50.0``, which conflicts with ModelOpt's minimum supported ``transformers`` version. The VILA-specific bootstrap (repo clone, ``requirements-vila.txt``) and loading paths in ``example_utils.py`` have been removed. | ||
| - Dropped **Phi-3-vision** and **Phi-4-multimodal** PTQ support in ``examples/hf_ptq`` (NVBug 6563509). Their bundled remote code predates Transformers v5 and no longer loads on any version ModelOpt supports (``transformers>=4.57``): Phi-4-multimodal requires ``transformers<4.52`` because it reaches ``prepare_inputs_for_generation`` through ``peft``, which needs ``PreTrainedModel`` to still inherit ``GenerationMixin``, and both models declare ``_tied_weights_keys`` as a list, which Transformers 5.x rejects. The support-matrix row, the ``phi4mm`` model type, the multimodal-detection heuristics that only ever matched these two (``vision_lora`` / ``audio_processor`` / ``embd_layer.image_embd_layer``), the ``Phi3Image`` / ``PhiImage`` embedding-export exclusions, and the ``modelopt_recipes/huggingface/phi4mm/`` recipes have been removed. Text-only Phi-3/Phi-4 and Phi-3.5-MoE are unaffected. |
There was a problem hiding this comment.
Bot comment.
This prior compatibility comment is still unresolved. The author confirmed Phi-3-vision was not tested on supported Transformers 4.57 and that its identified _tied_weights_keys failure applies to 5.x, so “no longer loads on any version ModelOpt supports” remains unsupported for that model. Please describe Phi-3-vision as a product/supersession removal (using the rationale from the author's reply), or provide the missing 4.57 repro/blocker. Keep the technical incompatibility claim scoped to Phi-4-MM where the version matrix supports it.
There was a problem hiding this comment.
Addressed in 17dfd3b — you were right that the entry was making an unverified claim.
The changelog now splits the two rationales. Phi-4-multimodal is described as unloadable on any supported version, which the matrix does support. Phi-3-vision is described as a supersession removal: "dropped alongside it: it is the older, superseded model in the same family, so with its successor unsupportable there is no reason to keep carrying the predecessor." A parenthetical records what was actually verified — it shares the list-valued _tied_weights_keys defect so is broken on Transformers 5.x, but does not hit the peft blocker. No 4.57 claim is made for it. The PR description carries the same split.
|
|
||
| # Only a sizing aid for ``infer_auto_device_map`` below; ``None`` when the model | ||
| # cannot be built on meta, in which case the estimate is skipped. | ||
| model = _build_meta_skeleton(from_config, config_for_init, model_kwargs2, architecture) |
There was a problem hiding this comment.
Bot comment.
[P1] Please release this parameter-only skeleton before loading the checkpoint. With include_buffers=False, parameters are meta tensors, but registered buffers and other tensors retained by the constructor are real CPU allocations. This local remains referenced while the right-hand side of the later model = auto_model_module.from_pretrained(...) materializes the actual checkpoint, so the two allocations overlap; disk-offload also builds the skeleton even though that branch never calls infer_auto_device_map. For models with large constructor buffers or caches, this can bypass max_cpu_memory_gb and OOM the memory-constrained path. Please skip skeleton construction in disk-offload mode and release model after device-map inference, before from_pretrained().
There was a problem hiding this comment.
Both points were correct, and they pushed the design somewhere better — addressed in 4e0157d, though not the way you suggested.
You were right on both counts against the code as it stood: Python evaluates the right-hand side before rebinding, so model = auto_model_module.from_pretrained(...) kept the probe alive for the whole checkpoint load, and with include_buffers=False its buffers are real CPU allocations. And the _disk_offload branch never touched the probe, so it was paying for one unused in exactly the memory-constrained path.
Rather than release the probe and skip it in disk-offload, the probe is gone. It only ever produced one boolean — will the weights fit on the GPUs, so should max_memory get the haircut — and that number is already on disk. metadata.total_size in the safetensors index equals what compute_module_sizes computed on the constructed model, exactly: Qwen3-8B 16381470720 B = 15.256 GiB, DeepSeek-R1-Distill-Llama-70B 141107412992 B = 131.417 GiB, both matching the meta model.
So _checkpoint_size_bytes() reads the index (falling back to summing shards, None if unreadable), and no model is constructed during device-map selection. That removes the overlap you flagged by construction, removes the disk-offload waste, and removes the original NVBug crash site entirely rather than tolerating it — Phi-4-multimodal now sizes at 10.383 GiB and reaches from_pretrained with no meta-tensor error. _build_meta_skeleton, its fallback warning, _resolve_init_config, the from_config resolution, and the accelerate init_empty_weights / infer_auto_device_map imports all went with it. Net 74 lines lighter.
Known approximation, worth flagging: total-bytes-vs-summed-GPU-budget ignores the per-device packing and no-split-module modelling infer_auto_device_map did. For a heuristic that only chooses whether to apply an 80% haircut, total size is the dominant term.
Tests cover the index path, the shard-sum fallback, a malformed index, capping only when the weights exceed the budget, and no cap when the size is unknown; the get_model tests also assert nothing is constructed during sizing.
There was a problem hiding this comment.
Superseded by 701180e — this code is back to its original form on main.
example_utils.py and its tests are restored to main except for the Phi-specific multimodal-detection heuristics. The meta-device skeleton, infer_auto_device_map, and the --gpu_max_mem_percentage cap all keep their original behavior, so there is nothing left in this thread to act on.
Reasoning: the cap is wanted exactly where it already fires — when the model is already offloading to CPU, where it costs little and the headroom is required. Every alternative explored on this branch (a more permissive skeleton, sizing from the checkpoint index, an unconditional budget) either changed behavior for models that fit today or moved the guard somewhere it does not belong, and all of it was for a crash that only ever affected the checkpoints this PR removes. NVBug 6563509 is resolved by dropping Phi-4-multimodal, not by changing the loader.
Phi-4-multimodal is dropped because it cannot load on any supported transformers version. Phi-3-vision is dropped because it is the superseded predecessor in the same family -- with the successor unsupportable there is no reason to keep the older model -- not because an equivalent 4.57 repro exists for it. The previous wording ran both models' rationale together and implied Phi-3-vision had been shown unloadable across the whole supported range, which overstates what was verified: it shares the list-valued _tied_weights_keys defect (so is broken on Transformers 5.x) but does not hit the peft/GenerationMixin blocker. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
get_model builds a device map to leave GPU headroom for calibration activations, and needs one boolean to do it: will the weights fit on the GPUs? It answered that by constructing a throwaway meta-device model and running infer_auto_device_map on it, then discarding the map and keeping only `"cpu" in .values()`. Constructing a model to learn its size means running the checkpoint's __init__, which is where this bug lives: remote code that derives a scalar from a real tensor (Phi-4-multimodal's conformer does int(torch.tensor(...))) cannot run under a meta device context. Both Transformers 4.x and 5.x load those models fine, so an optimization was killing loads it existed only to speed up. The number is already on disk. `metadata.total_size` in the safetensors index is the same sum `compute_module_sizes` computes -- exactly, verified on Qwen3-8B (16381470720 B = 15.256 GiB) and DeepSeek-R1-Distill-Llama-70B (141107412992 B = 131.417 GiB), matching what the meta model reported. `_checkpoint_size_bytes` reads it, falling back to summing shard sizes, and returns None when the layout is unreadable (no cap applied, as before). This removes the failure mode rather than tolerating it, and with it the retry/fallback machinery it needed: `_build_meta_skeleton`, its warning path, the `del` that kept the probe's real buffers from overlapping the checkpoint load, the disk-offload special case, `_resolve_init_config` and the `from_config` resolution that fed it, and the accelerate `init_empty_weights` / `infer_auto_device_map` imports. Net 74 lines lighter. config_dtype now comes from hf_config rather than the re-derived built-in config; both read the same config.json dtype field. Tests cover the index-metadata path, the shard-sum fallback, a malformed index, capping only when the weights exceed the GPU budget, and no cap when the size is unknown. Verified end to end that Phi-4-multimodal now sizes at 10.383 GiB and reaches from_pretrained without a meta-tensor error. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
| return hf_config | ||
| builtin_config_kwargs = {k: v for k, v in config_kwargs.items() if k != "trust_remote_code"} | ||
| path = Path(ckpt_path) | ||
| if not path.is_dir(): |
There was a problem hiding this comment.
Bot comment.
[P1] Preserve sizing for Hugging Face model IDs. This returns None whenever ckpt_path is not a local directory, but --pyt_ckpt_path explicitly accepts a Hugging Face model name and the README recommends passing the model card directly. Every org/model invocation therefore bypasses the headroom logic below; a large Hub model that device_map=auto spills to CPU can again fill GPU memory and OOM during calibration. Please resolve or download the small checkpoint index, or query Hub file metadata/cache, before returning unknown, and add a repository-ID test. Reserve the None fallback for genuinely unreadable layouts.
There was a problem hiding this comment.
Correct, and it is one of the reasons the sizing logic is now gone entirely in 1b6a79d.
You were right about the gap: --pyt_ckpt_path accepts a model card (its help says so, and the README uses openai/gpt-oss-20b at line 245), hf_ptq.py:578 passes it straight into get_model unresolved, and _checkpoint_size_bytes bailed on anything that was not a local directory. Every hub-ID run silently lost the guard.
Rather than resolve hub metadata, the cap itself has been removed. It was only ever wanted in the offload case, where it is close to free — the run is already streaming weights, and the headroom is required because at 100% packed calibration OOMs immediately. Applied to a model that does fit it would convert a fully resident load into an offloaded one, which is a large certain slowdown introduced where there was none. That is why the original condition fired only on spill, and knowing which side you are on is exactly what needs a constructed model — the thing NVBug 6563509 is about.
So device_map="auto" now sizes itself; from_pretrained runs its own infer_auto_device_map on the real model regardless (transformers/modeling_utils.py:1362). --use_seq_device_map is the supported answer to GPU OOM, and --gpu_max_mem_percentage applies there and to --offload_folder — which is what its help text already said: "the percentage of available GPU memory to use for loading the model when device_map is set to sequential."
There was a problem hiding this comment.
Superseded by 701180e — this code is back to its original form on main.
example_utils.py and its tests are restored to main except for the Phi-specific multimodal-detection heuristics. The meta-device skeleton, infer_auto_device_map, and the --gpu_max_mem_percentage cap all keep their original behavior, so there is nothing left in this thread to act on.
Reasoning: the cap is wanted exactly where it already fires — when the model is already offloading to CPU, where it costs little and the headroom is required. Every alternative explored on this branch (a more permissive skeleton, sizing from the checkpoint index, an unconditional budget) either changed behavior for models that fit today or moved the guard somewhere it does not belong, and all of it was for a crash that only ever affected the checkpoints this PR removes. NVBug 6563509 is resolved by dropping Phi-4-multimodal, not by changing the loader.
| # Cap the budget in that case. Sized from the checkpoint on disk rather than | ||
| # from a constructed model, so no checkpoint ``__init__`` runs here. | ||
| checkpoint_bytes = _checkpoint_size_bytes(ckpt_path) | ||
| gpu_budget = sum(size for dev, size in max_memory.items() if isinstance(dev, int)) |
There was a problem hiding this comment.
Bot comment.
[P1] Preserve per-device placement when deciding whether to reserve calibration headroom. Total checkpoint bytes fitting within the sum of GPU memory does not mean Accelerate can keep the model off CPU: parameters are indivisible and placement is per device. For example, two 9.5 GiB leaf parameters total 19 GiB across two 10 GiB GPUs, but infer_auto_device_map places one on GPU 1 and one on CPU, leaving the used GPU 95% full. This aggregate check reports that case as fitting and omits max_memory precisely when calibration may OOM. Please use a placement-aware or tensor-aware check, or a conservative condition that cannot produce this false fit, and add a regression test.
There was a problem hiding this comment.
The principle is right and the code is gone as of 1b6a79d, but the suggested direction would have been wrong, and it is worth recording why.
On the principle: yes, an aggregate byte count cannot reproduce per-device placement, since parameters are indivisible. (The worked example does not hold — two 9.5 GiB parameters across two 10 GiB GPUs place one each and both fit. Three 6 GiB blocks on two 10 GiB GPUs is the real shape: 18 GiB aggregate against 20 GiB, yet the third spills.)
On the fix: a "conservative condition that cannot produce a false fit" would have been a regression. The cap is only wanted when the model is already offloading, where it is close to free and the headroom is required — at 100% packed, calibration OOMs immediately. Applied to a model that does fit, it converts a fully resident load into an offloaded one: a large, certain slowdown introduced where there was none. So a false "does not fit" is the more expensive error here, and biasing the check toward capping trades a rare loud OOM the user can fix with a flag for a guaranteed slowdown across a whole band of models.
Since the check must not be biased in either direction, and since answering it accurately requires constructing the model — which is the whole of NVBug 6563509 — the cap has been removed instead. device_map="auto" sizes itself; from_pretrained runs its own infer_auto_device_map on the real model anyway. --use_seq_device_map is the supported answer to GPU OOM.
No regression test, because there is no longer a condition to regress.
There was a problem hiding this comment.
Superseded by 701180e — this code is back to its original form on main.
example_utils.py and its tests are restored to main except for the Phi-specific multimodal-detection heuristics. The meta-device skeleton, infer_auto_device_map, and the --gpu_max_mem_percentage cap all keep their original behavior, so there is nothing left in this thread to act on.
Reasoning: the cap is wanted exactly where it already fires — when the model is already offloading to CPU, where it costs little and the headroom is required. Every alternative explored on this branch (a more permissive skeleton, sizing from the checkpoint index, an unconditional budget) either changed behavior for models that fit today or moved the guard somewhere it does not belong, and all of it was for a crash that only ever affected the checkpoints this PR removes. NVBug 6563509 is resolved by dropping Phi-4-multimodal, not by changing the loader.
get_model built a throwaway meta-device model, ran infer_auto_device_map on it,
and -- if the weights would spill to CPU -- shrank max_memory by
gpu_max_mem_percentage to leave room for calibration activations.
Answering "will the weights fit" requires constructing the model, and that is
the whole of NVBug 6563509: remote code that derives a scalar from a real tensor
in __init__ (Phi-4-multimodal's conformer does int(torch.tensor(...))) cannot
run under the global torch.device("meta") context accelerate uses for
include_buffers=True. Both Transformers 4.x and 5.x load such models fine, so
the probe was killing loads it existed only to tune.
The probe is gone rather than repaired. Sizing it from the checkpoint on disk
instead was accurate but not free: it silently skipped Hugging Face model IDs
(`--pyt_ckpt_path` accepts a model card, and the README recommends it), and an
aggregate byte count cannot reproduce per-device placement, so it could report a
false fit near capacity.
Neither is worth solving, because the cap is only wanted in the offload case.
There it is close to free -- the run is already streaming weights, and the
headroom is required, since at 100% packed calibration OOMs immediately. Applied
to a model that does fit, it would convert a fully resident load into an
offloaded one: a large, certain slowdown introduced where there was none. That
asymmetry is why the old condition fired only on spill, and it means the check
must not be biased in either direction -- which rules out a conservative
threshold as well.
So device_map="auto" now sizes itself; from_pretrained runs its own
infer_auto_device_map on the real model regardless. --use_seq_device_map is the
supported answer to GPU OOM, and --gpu_max_mem_percentage applies there and to
--offload_folder, matching what its help text already documented ("when
device_map is set to sequential").
Verified Phi-4-multimodal now reaches from_pretrained with no meta-tensor error,
and no model is constructed during device-map selection.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
examples/hf_ptq/example_utils.py and its tests are restored to main except for the Phi-specific multimodal-detection heuristics (vision_lora, audio_processor, embd_layer.image_embd_layer, model_type == "phi4mm"), which only ever matched the two models being dropped. The meta-device skeleton, infer_auto_device_map, and the gpu_max_mem_percentage cap keep their original behavior. The cap is wanted exactly where it already fires -- when the model is already offloading to CPU, where it is close to free and the headroom is required. Every alternative explored here (a permissive skeleton, sizing from the checkpoint index, an unconditional budget) either changed behavior for models that fit today or moved the guard somewhere it does not belong, for a crash that only ever affected checkpoints this PR removes. NVBug 6563509 is therefore resolved by dropping Phi-4-multimodal, not by changing the loader. A remote-code checkpoint that computes scalars from real tensors in __init__ will still fail the meta-device build; that is a separate question if it ever affects a supported model. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
There was a problem hiding this comment.
Can you please update this part to drop ph4mm?
0.46 is unreleased, so the same section cannot both cite modelopt_recipes/huggingface/phi4mm/ as an existing pattern and delete it. nemotron_vl still ships and carries the example on its own. The 0.45 and 0.37 mentions are left alone: those releases shipped with the recipe present, and their entries are a record of what happened then. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Chenjie Luo <chenjiel@nvidia.com>
What does this PR do?
Type of change: Deprecation
Resolves NVBug 6563509, where
hf_ptq.pyon Phi-4-multimodal-instruct died withRuntimeError: Tensor.item() cannot be called on meta tensors.The crash is real but not fixable on our side, and it is not the reason the model
is unusable. Phi-4-multimodal's bundled remote code predates Transformers v5 and
does not load on any version in our supported range
(
transformers>=4.57,<5.15):peft.get_peft_modelreadsprepare_inputs_for_generation, gone since transformers 4.52 droppedGenerationMixinfromPreTrainedModelmodeling_phi4mm.py:1959_tied_weights_keysdeclared as a list; Transformers 5.x calls.keys()on it inpost_initmodeling_phi4mm.py:1937int(torch.tensor(...))in__init__, which cannot run on a meta device — the reported crashspeech_conformer_encoder.py:1435The model card pins
transformers==4.48.2/peft==0.13.2, so there is nooverlap with our floor and nothing on our side can bridge it. The model is
therefore dropped rather than worked around.
Phi-3-vision is dropped alongside it because it is the older, superseded model
in the same family — with its successor unsupportable there is no reason to
keep carrying the predecessor. This is a product-scope call, not a separate
compatibility finding: Phi-3-vision shares the list-valued
_tied_weights_keysdefect (
modeling_phi3_v.py:1214) and so is likewise broken on Transformers 5.x,but it does not hit the
peftblocker, and it was not re-verified on 4.57.Per the 0.46 changelog we have already bumped the floor to 4.57 and noted that
"Transformers 4.x support will be dropped in a future release", so any remaining
window closes on its own. Same reasoning already applied to VILA / NVILA in this
release.
Removed
examples/hf_ptq/README.md"Phi4MMForCausalLM": "phi4mm"fromMODEL_NAME_TO_TYPEvision_lora,audio_processor,embd_layer.image_embd_layer, and thephi4mmmodel-type check — in bothis_multimodal_modeland_is_multimodal_configPhi3Image/PhiImageexclusions inis_embeddinghf_ptq.pymodelopt_recipes/huggingface/phi4mm/and its references inmodelopt_recipes/ptq.mdNot changed: the device-map sizing path (meta-device skeleton,
infer_auto_device_map, and the--gpu_max_mem_percentagecap) keeps itsoriginal behavior. That cap is wanted exactly where it already fires — when the
model is already offloading to CPU, where it costs little and the headroom is
required. With the affected checkpoints removed, there is no supported model
that trips the meta-device build, so there is nothing to work around here.
Text-only Phi-3/Phi-4 and Phi-3.5-MoE are natively supported by
transformers and are untouched.
Testing
On H200,
nvcr.io/nvidia/tensorrt-llm/release(torch 2.12, transformers 5.5.4),against the real checkpoint:
4.48.2 / 4.49.0 / 4.50.0 / 4.51.3 and fails at 4.53.3 / 4.56.2 / 4.57.1
(
AttributeError: 'Phi4MMModel' object has no attribute 'prepare_inputs_for_generation') and at 5.5.4 (meta-init, then tied-keys).This is what establishes that no supported version works.
tests/examples/hf_ptq/test_example_utils.py— 28 passed.tests/examples/hf_ptq+tests/unit/torch/export— failure setidentical to the pre-change tree (GPU/model-dependent
test_vlm_ptq, plustest_quant_aware_conversionscoped-mapping tests), so none are introducedhere.
pre-commitclean on all changed files, including recipe validation.Before your PR is "Ready for review"
Phi-4-multimodal is removed, along with the
huggingface/phi4mm/ptq/*recipes. Phi-4-multimodal is already unloadable on every supported transformers
version, so no working workflow regresses; Phi-3-vision is a deliberate scope
removal as its superseded predecessor.
CONTRIBUTING.md: N/Atest_get_model_*/test_resolve_init_config_*tests are unchanged and stillpass.
Additional Information
Two related references were left in place deliberately; say the word and I'll
fold them in:
tests/examples/hf_ptq/test_deploy.pystill deploys the already-publishednvidia/Phi-4-multimodal-instruct-{NVFP4,FP8}checkpoints. Those artifactsexist and serve fine; this PR only removes the ability to produce them.
examples/torch_onnx/README.mdstill lists Phi-4-multimodal-instruct. Thatis a separate ONNX pipeline that does not go through
get_model()and was nottested here.
Earlier revisions of this branch also reworked the device-map sizing so the
meta-tensor crash could not occur. That was reverted in 701180e: the guard is
correct as written, and every alternative either changed behavior for models that
fit today or moved the guard somewhere it does not belong, for a crash that only
ever affected the checkpoints this PR removes.